home *** CD-ROM | disk | FTP | other *** search
- /* limn -- convert bitmaps to splines.
-
- Copyright (C) 1992 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include "config.h"
-
- #include "bzr.h"
- #include "cmdline.h"
- #include "font.h"
- #include "logreport.h"
- #include "getopt.h"
- #include "spline.h"
-
- #include "display.h"
- #include "fit.h"
- #include "main.h"
- #include "output-bzr.h"
- #include "pxl-outline.h"
-
-
- /* The resolution of the font we will read, in pixels per inch. We
- don't deal with nonsquare pixels. (-dpi) */
- string dpi = "300";
-
- /* Says which characters we should process. This is independent of the
- ordering in the font file. (-range) */
- int starting_char = 0;
- int ending_char = MAX_CHARCODE;
-
- static string read_command_line (int, string []);
-
- int
- main (int argc, string argv[])
- {
- int code;
- string font_name = read_command_line (argc, argv);
- bitmap_font_type f = get_bitmap_font (font_name, atou (dpi));
- string font_rootname = remove_suffix (basename (font_name));
-
- if (logging)
- log_file = xfopen (extend_filename (font_rootname, "log"), "w");
-
- /* Initializing the display might involve forking a process. We
- wouldn't want that process to get copies of open output files,
- since then when it exited, random stuff might get written to the
- end of the file. */
- init_display (f);
-
- if (strlen (BITMAP_FONT_COMMENT (f)) > 0)
- REPORT1 ("{%s}\n", BITMAP_FONT_COMMENT (f));
-
- if (output_name == NULL)
- output_name = font_rootname;
-
- bzr_start_output (output_name, f);
-
- /* The main loop: for each character, find the outline of the shape,
- then fit the splines to it. */
- for (code = starting_char; code <= ending_char; code++)
- {
- pixel_outline_list_type pixels;
- spline_list_array_type splines;
- char_info_type *c = get_char (font_name, code);
-
- if (c == NULL) continue;
-
- REPORT1 ("[%u ", code);
- if (logging)
- {
- LOG ("\n\n\f");
- print_char (log_file, *c);
- }
-
- x_start_char (*c);
- pixels = find_outline_pixels (*c);
- /* `find_outline_pixels' uses corners as the coordinates, instead
- of the pixel centers. So we have to increase the bounding box. */
- CHAR_MIN_COL (*c)--; CHAR_MAX_COL (*c)++;
- CHAR_MIN_ROW (*c)--; CHAR_MAX_ROW (*c)++;
-
- REPORT ("|");
- splines = fitted_splines (pixels);
-
- bzr_output_char (*c, splines);
-
- /* Flush output before displaying the character, in case the user
- is interested in looking at it and the online version
- simultaneously. */
- flush_log_output ();
-
- x_output_char (*c, splines);
- REPORT ("]\n");
-
- /* If the character was empty, it won't have a bitmap. */
- if (BITMAP_BITS (CHAR_BITMAP (*c)) != NULL)
- free_bitmap (&CHAR_BITMAP (*c));
-
- free_pixel_outline_list (&pixels);
- free_spline_list_array (&splines);
- }
-
- bzr_finish_output ();
- close_display ();
-
- close_font (font_name);
-
- return 0;
- }
-
- /* Reading the options. */
-
- /* This is defined in version.c. */
- extern string version_string;
-
- #define USAGE "Options:
- <font_name> should be a filename, possibly with a resolution, e.g.,
- `cmr10' or `cmr10.300'.\n" \
- GETOPT_USAGE \
- "align-threshold <real>: if either coordinate of the endpoints on a
- spline is closer than this, make them the same; default is .5.
- corner-always-threshold <angle-in-degrees>: if the angle at a pixel is
- less than this, it is considered a corner, even if it is within
- `corner-surround' pixels of another corner; default is 60.
- corner-surround <unsigned>: number of pixels on either side of a
- point to consider when determining if that point is a corner; default
- is 4.
- corner-threshold <angle-in-degrees>: if a pixel, its predecessor(s),
- and its successor(s) meet at an angle smaller than this, it's a
- corner; default is 100.
- display-continue: do not wait for you to hit return after displaying
- each character.
- display-grid-size <unsigned>: number of expanded pixels between the grid
- lines; default is 10.
- display-pixel-size <unsigned>: length of one side of the square that
- each pixel expands into; default is 9.
- display-rectangle-size <unsigned>: length of one side of the square
- we draw to represent pixels; default is 6. Must be less than
- display-pixel-size.
- do-display: show some information in a window, online.
- dpi <unsigned>: use a resolution of <unsigned>; default is 300.
- error-threshold <real>: subdivide fitted curves that are off by
- more pixels than this; default is 2.0.
- filter-alternative-surround <unsigned>: another choice for
- filter-surround; default is 1.
- filter-epsilon <real>: if the angles using filter-surround and
- filter-alternative-surround points differ by more than this, use the
- latter; default is 10.0.
- filter-iterations <unsigned>: smooth the curve this many times
- before fitting; default is 4.
- filter-percent <percent>: when filtering, use the old point plus this
- much of neighbors to determine the new point; default is 33.
- filter-surround <unsigned>: number of pixels on either side of a point
- to consider when filtering that point; default is 2.
- help: print this message.
- keep-knees: do not remove ``knees''---points on the inside of the
- outline that are between two others.
- line-reversion-threshold <real>: if a spline is closer to a straight
- line than this, weighted by the square of the curve length, keep it a
- straight line even if it is a list with curves; default is .01.
- line-threshold <real>: if the spline is not more than this far away
- from the straight line defined by its endpoints,
- then output a straight line; default is 1.
- log: write detailed progress reports to <font_name>.log.
- output-file <filename>: write to <filename> if it has a suffix and to
- `<filename>.bzr' if it doesn't. Default is `<font_name>.bzr'.
- range <char1>-<char2>: only process characters between <char1> and
- <char2>, inclusive.
- reparameterize-improve <percent>: if reparameterization
- doesn't improve the fit by this much, as a percentage, stop; default
- is 10.
- reparameterize-threshold <real>: if an initial fit is off by more
- pixels than this, don't bother to reparameterize; default is 30.
- subdivide-search <percent>: percentage of the curve from the initial
- guess for a subdivision point to look for a better one; default is 10.
- subdivide-surround <unsigned>: number of points on either side of a
- point to consider when looking for a subdivision point; default is 4.
- subdivide-threshold <real>: if a point is this close or closer to a
- straight line, subdivide there; default is .03.
- tangent-surround <unsigned>: number of points on either side of a
- point to consider when computing the tangent at that point; default is 3.
- verbose: print brief progress reports on stderr.
- version: print the version number of this program.
- "
-
- /* We return the name of the font to process. */
-
- static string
- read_command_line (int argc, string argv[])
- {
- int g; /* `getopt' return code. */
- int option_index;
- boolean explicit_dpi = false;
- boolean printed_version = false;
- struct option long_options[]
- = { { "align-threshold", 1, 0, 0 },
- { "corner-always-threshold", 1, 0, 0 },
- { "corner-surround", 1, 0, 0 },
- { "corner-threshold", 1, 0, 0 },
- { "do-display", 0, (int *) &wants_display, 1 },
- { "display-continue", 0, (int *) &display_continue, 1 },
- { "display-grid-size", 1, 0, 0 },
- { "display-pixel-size", 1, 0, 0 },
- { "display-rectangle-size", 1, 0, 0 },
- { "dpi", 1, (int *) &explicit_dpi, 1 },
- { "error-threshold", 1, 0, 0 },
- { "filter-alternative-surround",1, 0, 0 },
- { "filter-epsilon", 1, 0, 0 },
- { "filter-iterations", 1, 0, 0 },
- { "filter-percent", 1, 0, 0 },
- { "filter-secondary-surround", 1, 0, 0 },
- { "filter-surround", 1, 0, 0 },
- { "help", 0, 0, 0 },
- { "keep-knees", 0, (int *) &keep_knees, 1 },
- { "line-reversion-threshold", 1, 0, 0 },
- { "line-threshold", 1, 0, 0 },
- { "log", 0, (int *) &logging, 1 },
- { "output-file", 1, 0, 0 },
- { "range", 1, 0, 0 },
- { "reparameterize-improve", 1, 0, 0 },
- { "reparameterize-threshold", 1, 0, 0 },
- { "subdivide-search", 1, 0, 0 },
- { "subdivide-surround", 1, 0, 0 },
- { "subdivide-threshold", 1, 0, 0 },
- { "tangent-surround", 1, 0, 0 },
- { "verbose", 0, (int *) &verbose, 1 },
- { "version", 0, (int *) &printed_version, 1 },
- { 0, 0, 0, 0 } };
-
- while (true)
- {
- g = getopt_long_only (argc, argv, "", long_options, &option_index);
-
- if (g == EOF)
- break;
-
- if (g == '?')
- exit (1); /* Unknown option. */
-
- assert (g == 0); /* We have no short option names. */
-
- if (ARGUMENT_IS ("align-threshold"))
- align_threshold = atof (optarg);
-
- else if (ARGUMENT_IS ("corner-always-threshold"))
- corner_always_threshold = atof (optarg);
-
- else if (ARGUMENT_IS ("corner-surround"))
- corner_surround = atou (optarg);
-
- else if (ARGUMENT_IS ("corner-threshold"))
- corner_threshold = atou (optarg);
-
- else if (ARGUMENT_IS ("display-grid-size"))
- display_grid_size = atou (optarg);
-
- else if (ARGUMENT_IS ("display-pixel-size"))
- display_pixel_size = atou (optarg);
-
- else if (ARGUMENT_IS ("display-rectangle-size"))
- display_rectangle_size = atou (optarg);
-
- else if (ARGUMENT_IS ("dpi"))
- dpi = optarg;
-
- else if (ARGUMENT_IS ("error-threshold"))
- error_threshold = atof (optarg);
-
- else if (ARGUMENT_IS ("filter-alternative-surround"))
- filter_alternative_surround = atou (optarg);
-
- else if (ARGUMENT_IS ("filter-epsilon"))
- filter_epsilon = atof (optarg);
-
- else if (ARGUMENT_IS ("filter-iterations"))
- filter_iteration_count = atou (optarg);
-
- else if (ARGUMENT_IS ("filter-percent"))
- filter_percent = GET_PERCENT (optarg);
-
- else if (ARGUMENT_IS ("filter-surround"))
- filter_surround = atou (optarg);
-
- else if (ARGUMENT_IS ("help"))
- {
- fprintf (stderr, "Usage: %s [options] <font_name>.\n", argv[0]);
- fprintf (stderr, USAGE);
- exit (0);
- }
-
- else if (ARGUMENT_IS ("line-reversion-threshold"))
- line_reversion_threshold = atof (optarg);
-
- else if (ARGUMENT_IS ("line-threshold"))
- line_threshold = atof (optarg);
-
- else if (ARGUMENT_IS ("output-file"))
- output_name = optarg;
-
- else if (ARGUMENT_IS ("range"))
- GET_RANGE (optarg, starting_char, ending_char);
-
- else if (ARGUMENT_IS ("reparameterize-improve"))
- reparameterize_improvement = GET_PERCENT (optarg);
-
- else if (ARGUMENT_IS ("reparameterize-threshold"))
- reparameterize_threshold = atof (optarg);
-
- else if (ARGUMENT_IS ("subdivide-search"))
- subdivide_search = GET_PERCENT (optarg);
-
- else if (ARGUMENT_IS ("subdivide-surround"))
- subdivide_surround = atou (optarg);
-
- else if (ARGUMENT_IS ("subdivide-threshold"))
- subdivide_threshold = atof (optarg);
-
- else if (ARGUMENT_IS ("tangent-surround"))
- tangent_surround = atou (optarg);
-
- else if (ARGUMENT_IS ("version"))
- printf ("%s.\n", version_string);
-
- /* Else it was just a flag; getopt has already done the assignment. */
- }
-
- FINISH_COMMAND_LINE ();
- }
-